#include <gtest/gtest.h>
#include <thread>
#include "scheduler/sequence_scheduler.h"
#include "scheduler/reactive_sequence_scheduler.h"
#include "scheduler/reactive_fallback_scheduler.h"
#include "scheduler/reactive_if_then_else_scheduler.h"
#include "scheduler/scheduler_factory.h"
#include "../sample/navigation_task.h"
#include "../sample/battery_level_check.h"
#include "../sample/screen_return_zero_check.h"
#include "../sample/docking_task.h"
#include "../sample/screen_return_zero_task.h"

TEST(test_reactive_sequence_scheduler_demo, test_reactive_sequence_scheduler)
{
    auto navigationTask = task::TaskFactory<NavigationTask>::createTask("navigation_task");
    auto dockingTask = task::TaskFactory<DockingTask>::createTask("docking_task");
    auto batteryCheck = task::TaskFactory<BatteryLevelCheck>::createTask("battery_level_check");

    auto reactiveSequenceScheduler = scheduler::SchedulerFactory<scheduler::ReactiveSequenceScheduler>::createScheduler("navigation_scheduler");

    reactiveSequenceScheduler->appendExecuteTask(navigationTask);
    reactiveSequenceScheduler->appendExecuteTask(dockingTask);
    reactiveSequenceScheduler->setReactiveTask(batteryCheck);

    reactiveSequenceScheduler->run();

    EASE_INFO("done");
}

TEST(test_reactive_sequence_scheduler_demo_2, test_reactive_sequence_scheduler)
{
    auto navigationTask = task::TaskFactory<NavigationTask>::createTask("navigation_task");
    auto dockingTask = task::TaskFactory<DockingTask>::createTask("docking_task");
    auto batteryCheck = task::TaskFactory<BatteryLevelCheck>::createTask("battery_level_check");
    auto screen_return_zero_check = task::TaskFactory<ScreenReturnZeroCheck>::createTask("screen_return_zero_check");

    auto reactiveSequenceScheduler = scheduler::SchedulerFactory<scheduler::ReactiveSequenceScheduler>::createScheduler("navigation_scheduler");

    auto sequence_scheduler = scheduler::SchedulerFactory<scheduler::SequenceScheduler>::createScheduler("sequence_scheduler");
    sequence_scheduler->appendTask(screen_return_zero_check);

    reactiveSequenceScheduler->appendExecuteTask(navigationTask);
    reactiveSequenceScheduler->appendExecuteTask(dockingTask);
    reactiveSequenceScheduler->setReactiveTask(batteryCheck);
    reactiveSequenceScheduler->setReactiveTask(screen_return_zero_check);

    reactiveSequenceScheduler->run();

    EASE_INFO("done");
}

TEST(test_reactive_fallback_scheduler_demo, test_reactive_fallback_scheduler)
{
    auto navigationTask = task::TaskFactory<NavigationTask>::createTask("navigation_task");
    auto batteryCheck = task::TaskFactory<BatteryLevelCheck>::createTask("battery_level_check");

    auto reactiveSequenceScheduler = scheduler::SchedulerFactory<scheduler::ReactiveFallbackScheduler>::createScheduler("navigation_scheduler");

    reactiveSequenceScheduler->setReactiveTask(batteryCheck);
    reactiveSequenceScheduler->appendExecuteTask(navigationTask);

    reactiveSequenceScheduler->run();

    EASE_INFO("done");
}

TEST(test_while_do_else_scheduler_demo, test_while_do_else_scheduler)
{
    auto navigation_task = task::TaskFactory<NavigationTask>::createTask("navigation_task");
    auto battery_check = task::TaskFactory<BatteryLevelCheck>::createTask("battery_level_check");
    auto docking_task = task::TaskFactory<DockingTask>::createTask("docking_task");

    auto while_do_else_scheduler = scheduler::SchedulerFactory<scheduler::ReactiveIfThenElseScheduler>::createScheduler("whileDoElseScheduler");

    while_do_else_scheduler->setWhileConditionTask(battery_check);
    while_do_else_scheduler->setThenTask(navigation_task);
    while_do_else_scheduler->setElseTask(docking_task);

    while_do_else_scheduler->run();

    EASE_INFO("done");
}

TEST(test_while_do_else_scheduler_demo2, test_while_do_else_scheduler)
{
    auto navigation_task = task::TaskFactory<NavigationTask>::createTask("navigation_task");
    auto battery_check = task::TaskFactory<BatteryLevelCheck>::createTask("battery_level_check");
    auto docking_task = task::TaskFactory<DockingTask>::createTask("docking_task");

    auto while_do_else_scheduler = scheduler::SchedulerFactory<scheduler::ReactiveIfThenElseScheduler>::createScheduler("whileDoElseScheduler");

    while_do_else_scheduler->setElseTask(docking_task);
    while_do_else_scheduler->setThenTask(navigation_task);
    while_do_else_scheduler->setWhileConditionTask(battery_check);

    auto sequence_scheduler = scheduler::SchedulerFactory<scheduler::SequenceScheduler>::createScheduler("SequenceScheduler");
    sequence_scheduler->appendScheduler(while_do_else_scheduler);

    sequence_scheduler->run();

    EASE_INFO("done");
}

TEST(test_while_do_else_scheduler_condition_scheduler, test_while_do_else_scheduler)
{
    auto battery_check = task::TaskFactory<BatteryLevelCheck>::createTask("battery_level_check");
    auto screen_return_zero_check = task::TaskFactory<ScreenReturnZeroCheck>::createTask("screen_return_zero_check");
    auto navigation_task = task::TaskFactory<NavigationTask>::createTask("navigation_task");
    auto docking_task = task::TaskFactory<DockingTask>::createTask("docking_task");
    auto screen_return_zero_task = task::TaskFactory<ScreenReturnZeroTask>::createTask("screen_return_zero_task");

    auto sequence_scheduler = scheduler::SchedulerFactory<scheduler::SequenceScheduler>::createScheduler("sequence_scheduler");
    sequence_scheduler->appendTask(battery_check);
    sequence_scheduler->appendTask(screen_return_zero_check);

    auto while_do_else_scheduler = scheduler::SchedulerFactory<scheduler::ReactiveIfThenElseScheduler>::createScheduler("while_do_else_scheduler");

    while_do_else_scheduler->setElseTask(docking_task);
    while_do_else_scheduler->setThenTask(navigation_task);
    while_do_else_scheduler->setWhileConditionScheduler(sequence_scheduler);

    while_do_else_scheduler->run();

    EASE_INFO("done");
}

TEST(test_while_do_else_scheduler_condition_scheduler2, test_while_do_else_scheduler)
{
    auto battery_check = task::TaskFactory<BatteryLevelCheck>::createTask("battery_level_check");
    auto screen_return_zero_check = task::TaskFactory<ScreenReturnZeroCheck>::createTask("screen_return_zero_check");
    auto navigation_task = task::TaskFactory<NavigationTask>::createTask("navigation_task");
    auto docking_task = task::TaskFactory<DockingTask>::createTask("docking_task");
    auto screen_return_zero_task = task::TaskFactory<ScreenReturnZeroTask>::createTask("screen_return_zero_task");

    auto sequence_scheduler = scheduler::SchedulerFactory<scheduler::SequenceScheduler>::createScheduler("sequence_scheduler");
    sequence_scheduler->appendTask(battery_check);
    sequence_scheduler->appendTask(screen_return_zero_check);
    sequence_scheduler->appendTask(screen_return_zero_task);

    auto while_do_else_scheduler = scheduler::SchedulerFactory<scheduler::ReactiveIfThenElseScheduler>::createScheduler("while_do_else_scheduler");

    while_do_else_scheduler->setWhileConditionScheduler(sequence_scheduler);
    while_do_else_scheduler->setThenTask(navigation_task);
    while_do_else_scheduler->setElseTask(docking_task);

    while_do_else_scheduler->run();

    EASE_INFO("done");
}
